// ScriptureRef.cpp : implementation file
//

#include "stdafx.h"
#include "SwordBible.h"
#include "ScriptureRef.h"
#include "BibleSheet.h"
#include "CrossLinksMgr.h"

// CScriptureRef dialog
BOOL CScriptureRef::Detect = FALSE;
CStringArray CScriptureRef::verseArray;
  
CStringArray CScriptureRef::Xrefs;
CStringArray CScriptureRef::Footnotes;

IMPLEMENT_DYNAMIC(CScriptureRef, CPropertyPage)

CScriptureRef::CScriptureRef()
	: CPropertyPage(CScriptureRef::IDD)
{

}

CScriptureRef::~CScriptureRef()
{
}

void CScriptureRef::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_RICHEDIT_SCRIPREF, richCtrl);
}


BEGIN_MESSAGE_MAP(CScriptureRef, CPropertyPage)
  ON_COMMAND(ID_CROSSLINKSMGR, OnCrossLinksMgr)
  ON_COMMAND(ID_SCRIPREF_COPY, OnCopy)
  ON_COMMAND(ID_SCRIPREF_SELECTALL, OnSelectAll)
  ON_COMMAND(ID_SCRIPREF_ZOOM, OnZoom)
  ON_UPDATE_COMMAND_UI(ID_SCRIPREF_ZOOM, OnUpdateZoom)
  ON_WM_SIZE()
  ON_NOTIFY(EN_MSGFILTER, IDC_RICHEDIT_SCRIPREF, &CScriptureRef::OnEnMsgfilter)
END_MESSAGE_MAP()


// CScriptureRef message handlers
void CScriptureRef::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	CWnd* pWnd = GetDlgItem(IDC_RICHEDIT_SCRIPREF);

	// resize the rich edit  control
	if( ::IsWindow(pWnd ->GetSafeHwnd() )) 
	pWnd ->SetWindowPos(NULL,10,40,cx-20,cy-50,SWP_NOZORDER | SWP_NOACTIVATE);



	// TODO: Add your message handler code here
}

void CScriptureRef::SetText(CString text)
{
	if(  ((CBibleSheet*)GetParent())->GetActivePage() != this) {
	((CBibleSheet*)GetParent())->SetActivePage(this);
	}

	//words of christ in red
	text.Replace(_T("\\cf6"),_T("\\cf9"));

	// footnote tags are enclosed between href tags in bibles. Footnotes use color cf5 in the color table 
	// x reference tags are enclosed between href tags in bibles. cross references use color cf6 in the color table 
	text.Replace(_T("<a href=\"\">*n"),  _T("\\cf5\\b *n"));
	text.Replace(_T("<a href=\"\">*x"),  _T("\\cf6\\b *x"));
	text.Replace(_T("</a>"), _T("\\cf2\\b0 "));
	text.Replace(_T("<a href=\"\">"),  _T(" "));

	richCtrl.SetRTF(text);

  ZoomText();

  XLimits.Clear();
  if(Detect && CSwordBibleDoc::crossref_tags) SetXLimits();

  tips.Clear();
  if(Detect) DetectTips();

  Detect = FALSE;
 
}

void CScriptureRef::DetectTips()
{
  FINDTEXTEX ft;
	ft.chrg.cpMin = 0;
	ft.chrg.cpMax = -1;
	

	int start = 0;
  int count = verseArray.GetCount();
  int len = 0;
  CString tofind;


  for(int i =0; i < count; i++) {

  tofind = verseArray.GetAt(i);  // first verse to find
  ft.lpstrText =  tofind; 
  len = tofind.GetLength();
  	
	start = richCtrl.FindText(FR_DOWN , &ft); //find the verse

	if(start == -1) return;

	tips.Add(start, start + len - 1, tofind);
	
	ft.chrg.cpMin = start + 1;

	}

 verseArray.RemoveAll();

  
}

BOOL CScriptureRef::OnInitDialog()
{
	CDialog::OnInitDialog();

	richCtrl.SetEventMask(ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_SCROLLEVENTS);
	richCtrl.SendMessage(EM_EXLIMITTEXT,0,-1);

  LoadToolbar();

  Detect = FALSE;

  verseArray.RemoveAll();
	
	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}


// this function loads the toolbar on the bible page
int CScriptureRef::LoadToolbar(void)
{
	
  if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD
       | WS_VISIBLE | CBRS_TOP |  CBRS_FLYBY | CBRS_TOOLTIPS) ||
       !m_wndFormatBar.LoadToolBar(IDR_TOOLBAR_SCRIPREF))
   {
      TRACE0("Failed to create toolbar\n");
      return -1;      // fail to create
   }

   m_wndFormatBar.LoadTCToolBar(24, IDB_TOOLBAR_SCRIPREF, IDB_TOOLBAR_SCRIPREF,
                               IDB_TOOLBAR_SCRIPREF, RGB(255,255,255));


	// Position the control bars using RepositionBars. 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

	// Expand the size of the Toolbar window so all controls in it would fit
	CRect toolBarRect;
	CToolBarCtrl& formatBar = m_wndFormatBar.GetToolBarCtrl();
	formatBar.GetWindowRect(toolBarRect);
	ScreenToClient(toolBarRect);
	toolBarRect.left += 10  ;
	toolBarRect.right += 500  ;
	formatBar.MoveWindow(toolBarRect,TRUE);

  return 0;
}

void CScriptureRef::OnCrossLinksMgr()
{
   CCrossLinksMgr dlg;  
   dlg.DoModal();
}

void CScriptureRef::OnCopy() 
{
	// only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

  richCtrl.Copy();

 }

void CScriptureRef::OnSelectAll()
{
		// only the active page should handle the message
  if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

  richCtrl.SetSel(0,-1);

}

void CScriptureRef::OnZoom()
{
	// only the active page should handle the message
		if(  !( ((CPropertySheet*) GetParent())->GetActivePage()   == this) )  
	  return;

	CSwordBibleDoc::scripRefZoom = !(CSwordBibleDoc::scripRefZoom);

	ZoomText();

}

void CScriptureRef::ZoomText()
{
	if(CSwordBibleDoc::scripRefZoom) richCtrl.SendMessage(EM_SETZOOM, 5,4); //zoom by 1.25
	else richCtrl.SendMessage(EM_SETZOOM, 0,0);  // turn off zooming
}


void CScriptureRef::OnUpdateZoom(CCmdUI *pCmdUI)
{
	pCmdUI->SetCheck(CSwordBibleDoc::scripRefZoom);	
}
void CScriptureRef::OnEnMsgfilter(NMHDR *pNMHDR, LRESULT *pResult)
{
  MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);

  if (pMsgFilter->msg == WM_RBUTTONDOWN)   OnRightButtonDown();

  if(pMsgFilter->msg == WM_MOUSEMOVE)
	{ 
		CPoint point;                                            
    ::GetCursorPos(&point); //where is the mouse?


		 // change the coordinates of the point from Screen to that of richedit
		richCtrl.ScreenToClient(&point);

		int nchar =  richCtrl.CharFromPos(point);

		CString keylist = _T("");
    CString number = _T("");
		int lower = 0, upper = 0;
		if(tips.FromPos(nchar,lower, upper, keylist) == TRUE || XLimits.FromPos(nchar, lower, upper, number) == TRUE ) 
		SetCursor(CBibleSheet::m_hHandCursor);
	}


  if(pMsgFilter->msg == WM_LBUTTONDOWN ) OnLeftButtonDown();
	
	


  *pResult = 0;
}


void CScriptureRef::OnLeftButtonDown()
{
  	 CPoint point;                                            
     ::GetCursorPos(&point); //where is the mouse?

		 // change the coordinates of the point from Screen to that of richedit
		richCtrl.ScreenToClient(&point);

		int nchar =  richCtrl.CharFromPos(point);

		CString number = _T("");
		CString keyList = _T("");
		CString tip = _T("");
		int lower = 0, upper = 0;


    if(XLimits.FromPos(nchar, lower, upper, number))
		 {
	
			 CString dlgTitle =  _T("Scripture Cross-reference");       
       CBiblePage::DisplayReferenceVerses(number, tip);
		   CBibleSheet::DisplayReference(dlgTitle, tip);
       return;

		 }
	
    
    
    if(tips.FromPos(nchar,lower, upper, keyList) == FALSE)	
			return;     // no tooltip to display

    CSwordBibleDoc::key = (CStringA) keyList;

    CWnd* pWnd = AfxGetMainWnd();

	// Change the display in bible, notes, commentaries
	
	CBiblePage::ActiveMainFrameCommand = _T("ShowChapter");
	pWnd->SendMessageToDescendants(ID_BIBLEPAGE_COMMAND, 0,0);

	if(CSwordBibleDoc::notesSynch)
	{
	CNotesPage::ActiveMainFrameCommand = _T("BibleSynch");
	pWnd->SendMessageToDescendants(ID_NOTES_COMMAND,0,0);
	}

	if(CSwordBibleDoc::bottomSynch)
	{
	CBottomPage::ActiveMainFrameCommand = ("BibleSynch");
	pWnd->SendMessageToDescendants(ID_COMMENTARY_COMMAND,0,0);
	}  

  CBiblePage::ActiveMainFrameCommand = _T("highlight");
	pWnd->SendMessageToDescendants(ID_BIBLEPAGE_COMMAND, 0,0);



}

void CScriptureRef::OnRightButtonDown()
{
	
   CPoint point;                                            
  ::GetCursorPos(&point); //where is the mouse?
  CMenu menu; //lets display out context menu :) 
  menu.CreatePopupMenu();
  CMenu * pmenuPopup = &menu;
  DWORD dwSelectionMade; 
  if(pmenuPopup == NULL) return;

  UINT flags;

   for(int i = 0; i < REFERENCES_RMB_MENUITEMS; i++) {
      flags = MF_STRING;
      if(SBLocalize::ReferencesMenu[i].resID == ID_SEPARATOR) flags = MF_SEPARATOR;
      pmenuPopup->AppendMenu(flags,SBLocalize::ReferencesMenu[i].resID, SBLocalize::ResourceSet[ SBLocalize::ReferencesMenu[i].mapID ].menuStr );     
    }


  if(CSwordBibleDoc::scripRefZoom)	pmenuPopup->CheckMenuItem(ID_SCRIPREF_ZOOM,MF_CHECKED);


 dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|TPM_LEFTBUTTON|
                                                      TPM_RETURNCMD),
                                                    point.x, point.y, this); 

	

	
	switch (dwSelectionMade)
	{
	case ID_CROSSLINKSMGR:		     OnCrossLinksMgr();  break;
	case ID_SCRIPREF_COPY:		     OnCopy(); break;
	case ID_SCRIPREF_SELECTALL:    OnSelectAll(); break;
	case ID_SCRIPREF_ZOOM:         OnZoom(); break; 
  }

	
	pmenuPopup->DestroyMenu(); 



}



void CScriptureRef::AddXref(CString& VerseText, int verse)
{
	
	int found  = 0;
	int index  = 1;

	CString findtext;
	CString verseStr;
	CString indexStr;
	CStringArray x_label;	

	verseStr.Format(_T("%d"), verse);

	for(index = 1; index < 15; index++)
	{
	indexStr.Format(_T("%d"), index);
	findtext = _T("*x") + verseStr + _T(".") + indexStr;

	found = VerseText.Find(findtext);

	if(found != -1) x_label.Add(findtext);		
	}


	int c = 0;
	int count = x_label.GetCount();
	sword::AttributeList &xrefl = CSwordBibleDoc::pXrefModuleActive->getEntryAttributes()["Footnote"]; 

	for (sword::AttributeList::iterator& it = xrefl.begin(); it != xrefl.end() && c < count; it++) 
	{
		CString xtext= (CString) it->second["refList"];
		if(xtext.GetLength() >= 2)	Xrefs.Add( x_label.GetAt(c++) + _T("$$$") + xtext );
	}
								
	
					
}


void CScriptureRef::AddFootNotes(CString& VerseText, int verse)
{	
	int found  = 0;
	int index  = 1;

	CString findtext;
	CString verseStr;
	CString indexStr;
	CStringArray fn_label;
	CString fntext;

	verseStr.Format(_T("%d"), verse);

	for(index = 1; index < 15; index++)
	{
	indexStr.Format(_T("%d"), index);
	findtext = _T("*n") + verseStr + _T(".") + indexStr;

	found = VerseText.Find(findtext);

	if(found != -1) fn_label.Add(findtext);
		
	}


	int c = 0;
	int count = fn_label.GetCount();
	
	sword::AttributeList &fnl = CSwordBibleDoc::pXrefModuleActive->getEntryAttributes()["Footnote"]; 

	for (sword::AttributeList::iterator& it = fnl.begin(); it != fnl.end() && c < count; it++) 
	{
		fntext= it->second["body"];
		if(fntext.GetLength() > 1 && it->second["type"] != "crossReference" )	Footnotes.Add( fn_label.GetAt(c++) + " " + fntext );
	}

}



void CScriptureRef::SetXLimits()
{
	int count = Xrefs.GetCount();
	FINDTEXTEX ft1;
	ft1.chrg.cpMin = 0;
	ft1.chrg.cpMax = -1;
	int pos;
	CString left, right;
	int start, end;


	for(int i =0; i < count; i++)
	{
		CString str = Xrefs.GetAt(i);
		pos = str.Find(_T("$$$"));
		left = str.Left(pos);
		right = str.Mid(pos + 3);

		ft1.lpstrText = left;

		start = richCtrl.FindText(FR_DOWN , &ft1);
		end = start + left.GetLength() - 1;

		XLimits.Add(start, end, right);

		ft1.chrg.cpMin = start + 1;

	}
}


